package com.yonyou.pmclouds.workflow.util;

import com.yonyou.pmclouds.basecom.billstatus.BillStatusConst;
import com.yonyou.pmclouds.basecom.entity.SuperVO;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.basecom.runtime.RuntimeEnvironment;
import com.yonyou.pmclouds.basecom.util.BeanHelper;
import com.yonyou.pmclouds.basecom.util.CommonFieldConst;
import com.yonyou.pmclouds.externalservice.rmiitf.FailedExternalRecordMaintain;
import com.yonyou.pmclouds.task.entity.TaskConst;
import com.yonyou.pmclouds.task.entity.TaskVO;
import com.yonyou.pmclouds.task.rmiitf.TaskRemoteService;
import com.yonyou.pmclouds.workflow.entity.PMAssignInfo;
import com.yonyou.pmclouds.workflow.entity.ProcessTaskVO;
import com.yonyou.pmclouds.workflow.entity.StartFlowArgsVO;
import com.yonyou.pmclouds.workflow.service.ProcessRuntimeService;
import com.yonyou.pmclouds.workflow.service.ProcessTaskService;
import com.yonyou.pmclouds.workflow.service.rmiitf.IWorkFlowService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import yonyou.bpm.rest.request.task.TaskQueryParam;

import java.util.Date;

/**
 *  异步调用云审启动工作流接口
 *  @author zhangzhonghao
 */

@Component
@Slf4j
public class StartFlowExecutor extends BatchExecutor {

    @Autowired
    private ProcessRuntimeService processRuntimeService;
    @Autowired
    private TaskRemoteService taskRemoteService;
    @Autowired
    private IWorkFlowService workFlowService;
    @Autowired
    private ProcessTaskService processTaskService;
    @Autowired
    private FailedExternalRecordMaintain failedRecordMaintain;

    @Override
    public Object executeTaskImpl(Object value){

        log.debug("进入StartFlowExecutor");

        long startTime = System.currentTimeMillis();

        StartFlowArgsVO startFlowArgsVO = (StartFlowArgsVO) value;
        String billType = startFlowArgsVO.getBillType();
        String processKey = startFlowArgsVO.getProcessKey();
        PMAssignInfo assignedInfo = startFlowArgsVO.getAssignInfo();
        SuperVO businessVO = startFlowArgsVO.getBusinessVO();
        byte origBillStatus = startFlowArgsVO.getOriginalStatus();
        RuntimeEnvironment.setTenantId(startFlowArgsVO.getTenantId());
        RuntimeEnvironment.setLoginUserId(startFlowArgsVO.getUserId());

        log.debug("获取参数：billType = " + billType + ", processKey = " + processKey + ", tenantId = " + RuntimeEnvironment.getTenantId()
                + ", origBillStatus = " + origBillStatus);

        try {
            //之前单据状态为驳回时，视为再提交，不需要另起流程
            if (BillStatusConst.COMMON_REJECT_STATUS != origBillStatus){
                log.debug("启动审批流程");

                //启动审批流程
                startProcessInstance(businessVO, processKey, assignedInfo);
            } else{
                taskRemoteService.finishTask((String) businessVO.pkFiledValue(), null, BillStatusConst.COMMON_COMMIT_STATUS);
                //生成下一条待办任务
                genNextTask(businessVO);
            }

            log.debug("调用云审批接口启动工作流共耗时：" + (System.currentTimeMillis() - startTime));
        }catch (Exception e){
            log.error("启动审批流失败：", e);

            // 保存异常单据，并推送错误信息给制单人
            try {
                // 将单据状态回滚为自由态
                workFlowService.updateBillStatus(billType, businessVO, BillStatusConst.COMMON_FREE_STATUS);
                failedRecordMaintain.insert(businessVO, e.getMessage());

            } catch (BusinessException e1) {
                log.error("保存提交失败的单据信息失败：", e1);
            }

        }

        return value;
    }

    /**
     * 启动审批流程，未匹配到审批流程的单据，直接审批通过
     *
     * @param returnArg    业务单据VO
     * @param processKey   流程模型key
     * @param assignedInfo 已选中的指派信息
     */
    private void startProcessInstance(SuperVO returnArg, String processKey, PMAssignInfo assignedInfo) throws BusinessException, InterruptedException {
        log.debug("进入startProcessInstance：processKey = " + processKey);

        if (processKey != null) {
            if (assignedInfo != null) {
                processRuntimeService.startProcessInstanceWithAssign(processKey, returnArg, assignedInfo.getAssignInfo());
            } else {
                processRuntimeService.startProcessInstanceByKey(processKey, returnArg);
            }

            genNextTask(returnArg);

        } else {
            //任务表添加一条单据审批通过任务数据
            taskRemoteService.insertTaskVO(genMyLaunchVOs(returnArg));
        }

        log.debug("startProcessInstance方法执行完毕");
    }

    /**
     * 生成下一阶段的待办任务
     */
    private void genNextTask(SuperVO buziVO) throws BusinessException {
        TaskQueryParam param = new TaskQueryParam();
        param.setProcessInstanceBusinessKey((String) buziVO.pkFiledValue());

        ProcessTaskVO[] processTaskVOs = processTaskService.queryProcessTaskVOs(param);

        if (ArrayUtils.isEmpty(processTaskVOs))
            return;

        TaskVO[] taskVOs = genTaskVOs(buziVO, processTaskVOs);
        taskRemoteService.insertTaskVOs(taskVOs);
    }


    private TaskVO[] genTaskVOs(SuperVO superVO, ProcessTaskVO[] processTaskVOs) {

        TaskVO[] taskVOs = new TaskVO[processTaskVOs.length];
        for (int i = 0; i < processTaskVOs.length; i++) {
            TaskVO taskVO = new TaskVO();
            taskVO.setPk_bill((String) superVO.pkFiledValue());
            String pk_project = BeanHelper.getProperty(superVO, CommonFieldConst.PK_PROJECT) == null ?
                    (String) BeanHelper.getProperty(superVO, CommonFieldConst.PKPROJECT) :
                    (String) BeanHelper.getProperty(superVO, CommonFieldConst.PK_PROJECT);
            taskVO.setPk_project(pk_project);
            String creator = (String) BeanHelper.getProperty(superVO, CommonFieldConst.CREATOR);
            taskVO.setPk_sender(StringUtils.isBlank(creator) ? (String) BeanHelper.getProperty(superVO, CommonFieldConst.MODIFIER) : creator);
            String bill_type = BeanHelper.getProperty(superVO, CommonFieldConst.BILL_TYPE) == null ?
                    (String) BeanHelper.getProperty(superVO, CommonFieldConst.BILLTYPE) :
                    (String) BeanHelper.getProperty(superVO, CommonFieldConst.BILL_TYPE);
            taskVO.setSrc_bill_type(bill_type);

            taskVO.setBillstatus(BillStatusConst.COMMON_APPROVING_STATUS);
            taskVO.setTaskcreator(StringUtils.isBlank(creator) ? (String) BeanHelper.getProperty(superVO, CommonFieldConst.MODIFIER) : creator);
            taskVO.setPk_receiver(processTaskVOs[i].getPkReceiver());
            taskVO.setTask_status(TaskConst.TASK_TODO);
            taskVO.setLast_v_flag("Y");
            Date creationTime = (Date) BeanHelper.getProperty(superVO, CommonFieldConst.CREATIONTIME);
            taskVO.setCreationtime(creationTime == null ? (Date) BeanHelper.getProperty(superVO, CommonFieldConst.MODIFYTIME) : creationTime);
            taskVOs[i] = taskVO;
        }

        return taskVOs;
    }

    /**
     *给Task任务对象属性赋值，返回一个Task对象
     */
    private TaskVO genMyLaunchVOs(SuperVO superVO) {
        //创建一个任务表实体
        TaskVO taskVO = new TaskVO();
        //添加单据主键
        taskVO.setPk_bill((String) superVO.pkFiledValue());
        //获得项目主键
        String pk_project = BeanHelper.getProperty(superVO, CommonFieldConst.PK_PROJECT) == null ?
                (String) BeanHelper.getProperty(superVO, CommonFieldConst.PKPROJECT) :
                (String) BeanHelper.getProperty(superVO, CommonFieldConst.PK_PROJECT);
        //添加项目主键
        taskVO.setPk_project(pk_project);
        //添加任务发起者
        taskVO.setPk_sender((String) BeanHelper.getProperty(superVO, CommonFieldConst.CREATOR));
        //获取单据类型
        String bill_type = BeanHelper.getProperty(superVO, CommonFieldConst.BILL_TYPE) == null ?
                (String) BeanHelper.getProperty(superVO, CommonFieldConst.BILLTYPE) :
                (String) BeanHelper.getProperty(superVO, CommonFieldConst.BILL_TYPE);
        //添加单据类型
        taskVO.setSrc_bill_type(bill_type);
        //添加单据状态
        taskVO.setBillstatus((byte) BeanHelper.getProperty(superVO, CommonFieldConst.BILLSTATUS));
        //添加任务制造者
        taskVO.setTaskcreator((String) BeanHelper.getProperty(superVO, CommonFieldConst.CREATOR));
        taskVO.setPk_receiver(null);
        //添加任务状态，未结束为1
        taskVO.setTask_status(TaskConst.TASK_TODO);
        taskVO.setLast_v_flag("Y");
        //添加创建时间
        taskVO.setCreationtime((Date) BeanHelper.getProperty(superVO, CommonFieldConst.CREATIONTIME));

        return taskVO;
    }
}
